﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;
using System.Windows.Forms;

namespace LowLevelGraphics.Types.Interval
{
    /// <summary>
    /// The boundaries are momentarily included (>= ...)
    /// If they should be excluded use ONLY greater or smaller sign
    /// </summary>
    [DebuggerDisplay("[{m_nMin}, {m_nMax}]")]
    [TypeConverter(typeof(IntervalConverter<byte, ByteInterval>))] 
    public class ByteInterval : IComparable<ByteInterval>, ICloneable, ICustomTypeDescriptor
    {
        protected byte m_nMin = 0;
        protected byte m_nMax = 0;

        /// <summary>
        /// Default constructor
        /// </summary>
        public ByteInterval()
        {
        }

        /// <summary>
        /// This is the ByteInterval 
        /// </summary>
        /// <param name="_dMin">lower bound</param>
        /// <param name="_dMax">upper bound</param>
        public ByteInterval(byte _dMin, byte _dMax)
        {
            m_nMin = _dMin;
            m_nMax = _dMax;
        }

        /// <summary>
        /// Max value of this interval
        /// </summary>
        public byte Max
        {
            get { return m_nMax; }
            set { m_nMax = value; }
        }

        /// <summary>
        /// Min value of this interval
        /// </summary>
        public byte Min
        {
            get { return m_nMin; }
            set { m_nMin = value; }
        }

        /// <summary>
        /// Returns true, if the value is inside given interval
        /// </summary>
        /// <param name="_dValue"></param>
        /// <returns></returns>
        public bool Contains(byte _dValue)
        {
            return _dValue >= m_nMin && _dValue <= m_nMax;
        }

        /// <summary>
        /// Check if the current interval completely contains given interval
        /// </summary>
        /// <param name="_doubleInterval"></param>
        /// <returns></returns>
        public bool Contains(ByteInterval _doubleInterval)
        {
            return m_nMin<=_doubleInterval.m_nMin && m_nMax>= _doubleInterval.m_nMax;
        }

        /// <summary>
        /// This will check if an interval is overlapping, i.e. concrete:
        /// True if one of the given boundaries is contained inside the interval.
        /// The other boundary has to be outside the interval.
        /// </summary>
        /// <param name="_doubleInterval"></param>
        /// <returns></returns>
        public bool Intersects(ByteInterval _doubleInterval)
        {
            return 
                (Contains(_doubleInterval.m_nMax) && !Contains(_doubleInterval.m_nMin))
                || (Contains(_doubleInterval.m_nMin) && !Contains(_doubleInterval.m_nMax))
                ;
        }

        /// <summary>
        /// This returns the size of the interval.
        /// Also negative sizes are allowed to show the direction.
        /// Use Abs(Size) if direction is unimportant
        /// </summary>
        public double Size
        {
            get { return m_nMax - m_nMin; }
        }

        #region IComparable<DoubleInterval> Members

        /// <summary>
        /// An interval is bigger if its size is bigger
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int CompareTo(ByteInterval other)
        {
            return this.Size.CompareTo(other.Size);
        }

        #endregion

        /// <summary>
        /// Get interval as string in notation e.g. [0,1]
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("[{0},{1}]", m_nMin, m_nMax);
        }

        #region ICloneable Members

        /// <summary>
        /// Clone this interval
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return new ByteInterval(this.m_nMin, m_nMax);
        }

        #endregion

        #region ICustomTypeDescriptor Members

        public AttributeCollection GetAttributes()
        {
            return null;
        }

        public string GetClassName()
        {
            return TypeDescriptor.GetClassName(this, true);
        }

        public string GetComponentName()
        {
            throw new NotImplementedException();
        }

        public TypeConverter GetConverter()
        {
            return null;
        }

        public EventDescriptor GetDefaultEvent()
        {
            return null;
        }

        public PropertyDescriptor GetDefaultProperty()
        {
            return null;
        }

        public object GetEditor(Type editorBaseType)
        {
            return typeof(NumericUpDown);
        }

        public EventDescriptorCollection GetEvents(Attribute[] attributes)
        {
            return TypeDescriptor.GetEvents(this, attributes);
        }

        public EventDescriptorCollection GetEvents()
        {
            return TypeDescriptor.GetEvents(this);
        }

        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            return TypeDescriptor.GetProperties(this);
        }

        public PropertyDescriptorCollection GetProperties()
        {
            return null;
        }

        public object GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }

        #endregion
    }
}
